/**
 * @file   NewickTree.h
 * @author Scanagatta Mauro - Alberto Franco
 *
 * This file contains the implementation of the class that handle the
 * Newick format. Serialization and Deserialization is done separately.
 */
#ifndef NEWICK_TREE__H__
#define NEWICK_TREE__H__

#include <set>

namespace Biopool
{

typedef std::set<int> intSet;
class NewickTreeFactory;

/**
 * All methods in the class are inlined in order to speed up the appication.
 * Probably they would be inlined by the compiler, anyway we put them here to
 * avoid this problem and have them inlined.
 */
class NewickTree 
{
    friend class NewickTreeFactory; ///< Friend class declaration.
public:
    
    /// Default contructor
    NewickTree();
    
    /// Actual class that store the data.
    class Node 
    {
        friend class NewickTreeFactory; ///< Friend class declaration.
    public:
        
        /// Default contructor
        Node():
            objectRef(0), rightChild(0), leftChild(0), branchLength(-1.0) { }
    
        /// Node constuctor with two child
        Node(float length, intSet * sequenceSet, Node * right, Node * left):
            objectRef(sequenceSet), rightChild(right), leftChild(left), branchLength(length)
        { }
        
        /// Leaf contructor - distance in the leafs is zero.
        Node(intSet * sequenceSet) : objectRef(sequenceSet), rightChild(0), leftChild(0), branchLength(0.0)
        { }
        
        /// Return if the node is a leaf
        bool isLeaf() const 
        {
            return (!rightChild && !leftChild);
        }
        
        /// Return actual brach distance. 
        double getDistance () const 
        { 
            return branchLength;
        }

        /// Return actual brach distance.
        intSet * getSequencesSet () const
        {
            return objectRef;
        }

        /// Return left child of the node.
        Node * getLeftChild()
        {
            return leftChild;
        }

        /// Return the right child of the node.
        Node * getRightChild()
        {
            return rightChild;
        }
        
    private:
    
        intSet* objectRef;      ///< Reference to the object stored in the tree
        Node*   rightChild;     ///< Right tree child   
        Node*   leftChild;      ///< Left tree child
        double  branchLength;   ///< Distance from the tree
        
    }; // end class Node <------------------------------------------------------

    NewickTree(Node * rootNode); ///< Rooted tree build 

    Node * getRoot(); ///< Returns the root to handle the tree.
    
private:
    
    Node* root; ///< Tree root
    
}; // end class NewickTree <----------------------------------------------------


} /* namespace */

#endif // NEWICK_TREE__H__
